﻿using System;
using System.Linq;
using System.Security.Cryptography;
using SharpArch.NHibernate.Web.Mvc;
using ToyStore.Domain.Common;
using ToyStore.Domain.Contracts.Tasks;
using ToyStore.Domain.System;
using ToyStore.Infrastructure;
using ToyStore.Tasks;
using ToyStore.Web.Mvc.Authentication;
using ToyStore.Web.Mvc.Common;
using MvcContrib;
using System.Web.Mvc;
using ToyStore.Domain.Store;
using NHibernate.Mapping;
using System.Collections.Generic;
using PagedList;

namespace ToyStore.Web.Mvc.Controllers
{
	/// <summary>
	/// Główny kontroler.
	/// </summary>
	public class HomeController : Controller
	{
		/// <summary>
		/// Dostep do bazy danych użytkownikow.
		/// </summary>
		private readonly IExRepository<User> _userRepository;
		/// <summary>
		/// Dostep do bazy danych użytkownikow.
		/// </summary>
		private readonly IExRepository<Product> _productRepository;
		/// <summary>
		/// Dostęp do bazy danych koszk.
		/// </summary>
		private readonly IExRepository<Cart> _cartRepository;
		/// <summary>
		/// 
		/// </summary>
		private readonly ICartTask _cartTask;

		/// <summary>
		/// Konstruktor.
		/// </summary>
		/// <param name="userRepository"></param>
		/// <param name="productRepository"> </param>
		/// <param name="cartRepository"> </param>
		/// <param name="cartTask"> </param>
		public HomeController(IExRepository<User> userRepository, IExRepository<Product> productRepository, IExRepository<Cart> cartRepository, ICartTask cartTask)
		{
			_userRepository = userRepository;
			_productRepository = productRepository;
			_cartRepository = cartRepository;
			_cartTask = cartTask;
		}

		/// <summary>
		/// Strona główna serwisu.
		/// </summary>
		/// <returns></returns>
		//[OutputCache(Duration = 30)]
		public ActionResult Index()
		{
			ViewBag.Bestsellers = _productRepository.GetQuery().Take(6).ToList();
			ViewBag.News = _productRepository.GetQuery().OrderByDescending(x => x.Name).Take(6).ToList();
			return View();
		}

		/// <summary>
		/// Logowanie użytkowników.
		/// </summary>
		/// <param name="userName">Nazwa użytkownika.</param>
		/// <param name="password">Hasło użytkownika.</param>
		/// <param name="returnUrl"> </param>
		/// <returns></returns>
		[HttpPost]
		[ValidateAntiForgeryToken]
		[Transaction]
		public ActionResult LogOn(string userName, string password, string returnUrl)
		{
			try
			{
				string pass;
				using (MD5 md5Hash = MD5.Create())
				{
					pass = Md5Helper.GetMd5Hash(md5Hash, password);
				}

				var user = _userRepository.GetQuery().FirstOrDefault(u => u.UserName == userName && u.Password == pass);

				if (user != null)
				{
					WebAuthentication.CreatePrincipal(user);

					// Jesli sie logujemy i mamy koszyk w sesji, wowczas zapisujemy ze koszyk nie nalezu juz do anonimowego uzytkownika.
					if (HttpContext.Session[CartTask.CartSessionGuid] != null)
					{
						Cart cartFromSession = (Cart)HttpContext.Session[CartTask.CartSessionGuid];
						Cart cartFromDb = _cartTask.GetCartByGuid(cartFromSession.CartGuid);
						cartFromDb.User = user;
						_cartRepository.SaveOrUpdate(cartFromDb);
					}

					// Zawsze prubujemy pobrac najnowszy koszyk z bazy.
					Cart cart = _cartRepository.GetQuery().Where(c => c.IsDeleted == false).OrderByDescending(c => c.CreationDate).FirstOrDefault();
					if (cart != null)
					{
						HttpContext.Session[CartTask.CartSessionGuid] = cart;
					}

					if (!string.IsNullOrWhiteSpace(returnUrl))
					{
						return RedirectPermanent(returnUrl);
					}
					return this.RedirectToAction(c => c.Index());
				}

				TempData[ActionConfirmation.TempDataKey] = ActionConfirmation.CreateError("Podałeś niepoprawną nazwę użytkownika bądź hasło");
				return this.RedirectToAction(c => c.Index());
			}
			catch
			{
				TempData[ActionConfirmation.TempDataKey] = ActionConfirmation.CreateError("Podczas logowania wystąpił błąd");
				return this.RedirectToAction(c => c.Index());
			}
		}

		/// <summary>
		/// Wylogowywanie użytkownika.
		/// </summary>
		/// <returns></returns>
		[HttpGet]
		public ActionResult LogOut()
		{
			WebAuthentication.RemovePrincipal();
			return this.RedirectToAction<HomeController>(c => c.Index());
		}

		/// <summary>
		/// Sprawdzenie czy podany login jest dostepny.
		/// </summary>
		/// <param name="user"></param>
		/// <returns></returns>
		public JsonResult UserNameAvailable(User user)
		{
			if (user == null) throw new ArgumentNullException("user");

			// Pobieramy uzytkownika po loginie.
			User u = _userRepository.GetQuery().FirstOrDefault(l => l.UserName == user.UserName);

			// Jesli nie ma uzytkownika lub jest to uzytkownik dla ktorego sprawdzamy.
			if (u == null || u.Id == user.Id)
			{
				return Json(true, JsonRequestBehavior.AllowGet);
			}
			return Json("The specified login is busy.", JsonRequestBehavior.AllowGet);
		}

		/// <summary>
		/// Szczegóły koszyka.
		/// </summary>
		/// <returns></returns>
		public ActionResult CartDetails()
		{
			if (HttpContext.Session[CartTask.CartSessionGuid] != null)
			{
				Cart cart = (Cart)HttpContext.Session[CartTask.CartSessionGuid];
				ViewBag.CartAmount = cart.Amount;
				ViewBag.CartSum = cart.SumPriceBrutto;
			}

			return View();
		}

		/// <summary>
		/// Kasa.
		/// </summary>
		/// <returns></returns>
		[HttpGet]
		public ActionResult LogOnPage(string returnUrl)
		{
			ViewBag.ReturnUrl = returnUrl;
			return View();
		}

		[HttpPost]
		[ValidateAntiForgeryToken]
		public ActionResult LogOnPage(string userName, string password, string returnUrl)
		{
			return LogOn(userName, password, returnUrl);
		}
	}
}
